package com.flyxteam.commons.dao.mybatis.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.SqlSessionUtils;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.flyxteam.commons.dao.mybatis.api.condition.Condition;
import com.flyxteam.commons.dao.mybatis.api.condition.ConditionBuilder;
import com.flyxteam.commons.dao.mybatis.api.exception.MybatisArgumentException;
import com.flyxteam.commons.dao.mybatis.api.exception.MybatisDataAccessException;
import com.flyxteam.commons.dao.mybatis.core.constants.ConditionSign;
import com.flyxteam.commons.dao.mybatis.core.constants.MybatisConstant;
import com.flyxteam.commons.dao.mybatis.core.sqlbuilder.SqlBuilder;
import com.flyxteam.commons.dao.mybatis.core.sqlbuilder.SqlBuilderFactory;
import com.flyxteam.commons.dao.mybatis.core.utils.EntityUtil;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;

/**
 * 对外接口，提供了增删改查功能
 * @author yuzh
 *
 */
public class MybatisTemplate extends SqlSessionDaoSupport implements MybatisDao {

	private final static Logger LOGGER = LoggerFactory.getLogger(MybatisTemplate.class);
	
	// 批量保存每批次数量
	private final static int INSERT_BATCH_NUM = 1000;
	
	@Override
	public int insert(Object o) {
		if(o == null) {
			LOGGER.error("insert object cannot be null");
			throw new MybatisDataAccessException("insert object cannot be null");
		}
		String tableName = EntityUtil.getTableNameFromEntity(o.getClass(), isMapUnderscoreToCamelCase());
		Map<String, Object> columns = new HashMap<String, Object>();
		try {
			EntityUtil.entity2Map(o, columns,  isMapUnderscoreToCamelCase());
		} catch (IllegalArgumentException e) { 
			LOGGER.error("build insert sql param error", e);
			throw new MybatisDataAccessException("build insert sql param error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("build insert sql param error", e);
			throw new MybatisDataAccessException("build insert sql param error", e);
		}

		return insert(tableName, columns);
	}

	@Override
	public int insert(String tableName, Map<String, Object> columns) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		if(columns == null || columns.isEmpty()) {
			LOGGER.error("insert object cannot be null");
			throw new MybatisDataAccessException("insert object cannot be null");
		}
		SqlBuilder insertSqlBuilder = SqlBuilderFactory.insertSqlBuilder(tableName, columns);
		return insertCore(insertSqlBuilder);
	}

	@Override
	public void insertBatch(List<? extends Object> l) {
		if(l == null || l.isEmpty()) {
			LOGGER.error("insert object cannot be null");
			throw new MybatisDataAccessException("insert object cannot be null");
		}
		String tableName = EntityUtil.getTableNameFromEntity(l.get(0).getClass(), isMapUnderscoreToCamelCase());
		List<Map<String, Object>> columnList = new ArrayList<>(l.size());
		try {
			EntityUtil.entityList2Map(l, columnList, isMapUnderscoreToCamelCase());
		} catch (IllegalArgumentException e) {
			LOGGER.error("build insert sql param error", e);
			throw new MybatisDataAccessException("build insert sql param error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("build insert sql param error", e);
			throw new MybatisDataAccessException("build insert sql param error", e);
		}

		insertBatch(tableName, columnList);
	}
	

	@Override
	public void insertBatch(String tableName, List<Map<String, Object>> l) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		if(l == null || l.isEmpty()) {
			LOGGER.error("insert object cannot be null");
			throw new MybatisDataAccessException("insert object cannot be null");
		}
		
		List<List<Map<String, Object>>> insertBatchList = getInsertBatchList(l);
		for (List<Map<String, Object>> list : insertBatchList) {
			SqlBuilder insertSqlBuilder = SqlBuilderFactory.insertSqlBuilder(tableName, list);
			insertBatchCore(insertSqlBuilder);
		}
	}
	
	@Override
	public int updateByPk(Object o) {
		if(o == null) {
			LOGGER.error("update object cannot be null");
			throw new MybatisDataAccessException("update object cannot be null");
		}
		String tableName = EntityUtil.getTableNameFromEntity(o.getClass(), isMapUnderscoreToCamelCase());
		String pkColumnName = EntityUtil.getPkColumnName(o.getClass(), isMapUnderscoreToCamelCase());
		Map<String, Object> updateColumns = new HashMap<String, Object>();
		try {
			EntityUtil.entity2Map(o, updateColumns,  isMapUnderscoreToCamelCase());
		} catch (IllegalArgumentException e) {
			LOGGER.error("build sql param error", e);
			throw new MybatisDataAccessException("build sql param error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("build sql param error", e);
			throw new MybatisDataAccessException("build sql param error", e);
		}
		Object pkColumnVallue = updateColumns.get(pkColumnName);
		// 移除主键字段（主键作为条件字段，不参与set操作）
		updateColumns.remove(pkColumnName);
		
		return updateByPk(tableName, pkColumnName, pkColumnVallue, updateColumns);
	}

	@Override
	public int updateByPk(String tableName, String pkColumnName, Object pkColumnValue,
			Map<String, Object> updateColumnMap) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		if(StringUtils.isBlank(pkColumnName)) {
			LOGGER.error("pk column name cannot be null");
			throw new MybatisArgumentException("pk column name cannot be null");
		}
		if(pkColumnValue == null) {
			LOGGER.error("pk value cannot be null");
			throw new MybatisArgumentException("pk value cannot be null");
		}
		if(updateColumnMap == null || updateColumnMap.isEmpty()) {
			LOGGER.error("update columns cannot be null");
			throw new MybatisDataAccessException("update columns cannot be null");
		}
		ConditionBuilder cb = new ConditionBuilder();
		List<Condition> conditionList = cb.and(pkColumnName, ConditionSign.EQ, pkColumnValue).getConditionList();
		SqlBuilder updateSqlBuilder = SqlBuilderFactory.updateSqlBuilder(tableName, updateColumnMap, conditionList);
		String sql = updateSqlBuilder.buildSqlString();
		Map<String, Object> sqlParam = updateSqlBuilder.getSqlParam();
		sqlParam.put("sql", sql);
		return getSqlSession().update(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_UPDATE, sqlParam);
	}

//	@Override
//	public int updateByCondition(Object o, List<ConditionBean> conditionList) {
//		return 0;
//	}

//	@Override
//	public int updateByCondition(String tableName, Map<String, Object> updateColumnMap,
//			List<ConditionBean> conditionList) {
//		return 0;
//	}

//	@Override
//	public int updateByCondition(Object o, Object... conditionList) {
//		return 0;
//	}

//	@Override
//	public int updateByCondition(String tableName, Map<String, Object> updateColumnMap, Object... conditionList) {
//		return 0;
//	}

	@Override
	public int deleteByPk(String tableName, String pkColumnName, Object pkColumnValue) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		if(StringUtils.isBlank(pkColumnName)) {
			LOGGER.error("pk column name cannot be null");
			throw new MybatisArgumentException("pk column name cannot be null");
		}
		if(pkColumnValue == null) {
			LOGGER.error("pk value cannot be null");
			throw new MybatisArgumentException("pk value cannot be null");
		}
		Map<String, Object> sqlParam = buildPkCondition(tableName, pkColumnName, pkColumnValue);
		return getSqlSession().delete(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_DELETE_BY_PK, sqlParam);
	}

	@Override
	public int deleteByPk(Class<? extends Object> c, Object pkColumnValue) {
		if(pkColumnValue == null) {
			LOGGER.error("pk value cannot be null");
			throw new MybatisArgumentException("pk value cannot be null");
		}
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		String pkColumnName = EntityUtil.getPkColumnName(c, isMapUnderscoreToCamelCase());
		if(StringUtils.isBlank(pkColumnName)) {
			LOGGER.error("pk column name cannot be null");
			throw new MybatisArgumentException("pk column name cannot be null");
		}
		Map<String, Object> sqlParam = buildPkCondition(tableName, pkColumnName, pkColumnValue);
		return getSqlSession().delete(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_DELETE_BY_PK, sqlParam);
	}

//	@Override
//	public int deleteByCondition(String tableName, List<ConditionBean> conditionList) {
//		return 0;
//	}

//	@Override
//	public <T> int deleteByCondition(Class<T> c, List<ConditionBean> conditionList) {
//		return 0;
//	}

//	@Override
//	public int deleteByCondition(Object condition) {
//		return 0;
//	}

//	@Override
//	public int deleteByCondition(String tableName, Object... conditionList) {
//		return 0;
//	}

//	@Override
//	public <T> int deleteByCondition(Class<T> c, Object... conditionList) {
//		return 0;
//	}

	@Override
	public <T> T selectByPk(Class<T> c, Object pkColumnValue) {
		if(pkColumnValue == null) {
			LOGGER.error("pk value cannot be null");
			throw new MybatisArgumentException("pk value cannot be null");
		}
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		String pkColumnName = EntityUtil.getPkColumnName(c, isMapUnderscoreToCamelCase());
		if(StringUtils.isBlank(pkColumnName)) {
			LOGGER.error("pk column name cannot be null");
			throw new MybatisArgumentException("pk column name cannot be null");
		}
		Map<String, Object> sqlParam = buildPkCondition(tableName, pkColumnName, pkColumnValue);
		Map<String, Object> selectOne = getSqlSession().selectOne(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_SELECT_BY_PK, sqlParam);
		
		T t = null;
		try {
			t = c.newInstance();
			EntityUtil.map2Entity(selectOne, t, isMapUnderscoreToCamelCase());
		} catch (InstantiationException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		}
		
		return t;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> selectByPk(String tableName, String pkColumnName, Object pkColumnValue) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		if(StringUtils.isBlank(pkColumnName)) {
			LOGGER.error("pk column name cannot be null");
			throw new MybatisArgumentException("pk column name cannot be null");
		}
		if(pkColumnValue == null) {
			LOGGER.error("pk value cannot be null");
			throw new MybatisArgumentException("pk value cannot be null");
		}
		Map<String, Object> sqlParam = buildPkCondition(tableName, pkColumnName, pkColumnValue);
		return getSqlSession().selectOne(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_SELECT_BY_PK, sqlParam);
	
	}

	@Override
	public List<Map<String, Object>> select(String tableName, List<Condition> conditionList) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		SqlBuilder selectSqlBuilder = SqlBuilderFactory.selectSqlBuilder(tableName, conditionList);
		return selectCore(selectSqlBuilder);
	}
	
	@Override
	public <T> List<T> select(Class<T> c, List<Condition> conditionList) {
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		List<Map<String, Object>> ml = select(tableName, conditionList);
		List<T> tl = new ArrayList<T>();
		try {
			EntityUtil.mapList2Entity(ml, tl, c, isMapUnderscoreToCamelCase());
		} catch (InstantiationException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		}
		
		return tl;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> select(T condition) {
		Class<T> c = (Class<T>) condition.getClass();
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		List<Condition> conditionList = null;
		try {
			conditionList = EntityUtil.entity2Condition(condition, isMapUnderscoreToCamelCase());
		} catch (IllegalArgumentException e) {
			LOGGER.error("build condition error", e);
			throw new MybatisArgumentException("build condition error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("build condition error", e);
			throw new MybatisArgumentException("build condition error", e);
		}
		List<Map<String, Object>> ml = select(tableName, conditionList);
		
		List<T> tl = new ArrayList<T>();
		try {
			EntityUtil.mapList2Entity(ml, tl, c, isMapUnderscoreToCamelCase());
		} catch (InstantiationException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		}
		
		return tl;
	}
	
//	@Override
//	public List<Map<String, Object> select(String tableName, Object... conditionList) {
//		return null;
//	}

//	@Override
//	public <T> List<T> select(Class<T> c, Object... conditionList) {
//		return null;
//	}
	
	@Override
	public <T> List<T> select(Class<T> c) {
		return select(c, null);
	}
	
	@Override
	public List<Map<String, Object>> select(String tableName) {
		return select(tableName, null);
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, List<Condition> conditionList, PageBounds pageBounds) {
		if(StringUtils.isBlank(tableName)) {
			LOGGER.error("table name cannot be null");
			throw new MybatisDataAccessException("table name cannot be null");
		}
		SqlBuilder selectSqlBuilder = SqlBuilderFactory.selectSqlBuilder(tableName, conditionList);
		return selectPageCore(selectSqlBuilder, pageBounds);
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, List<Condition> conditionList, int page, int limit) {
		return selectPage(tableName, conditionList, new PageBounds(page, limit));
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, List<Condition> conditionList, int page, int limit, String orderExp) {
		return selectPage(tableName, conditionList, new PageBounds(page, limit, Order.formString(orderExp)));
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, List<Condition> conditionList, PageBounds pageBounds) {
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		List<Map<String, Object>> ml = selectPage(tableName, conditionList, pageBounds);
		List<T> tl = new ArrayList<T>();
		try {
			EntityUtil.mapList2Entity(ml, tl, c, isMapUnderscoreToCamelCase());
		} catch (InstantiationException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		}
		
		return tl;
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, List<Condition> conditionList, int page, int limit) {
		return selectPage(c, conditionList, new PageBounds(page, limit));
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, List<Condition> conditionList, int page, int limit, String orderExp) {
		return selectPage(c, conditionList, new PageBounds(page, limit, Order.formString(orderExp)));
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> selectPage(T condition, PageBounds pageBounds) {
		Class<T> c = (Class<T>) condition.getClass();
		String tableName = EntityUtil.getTableNameFromEntity(c, isMapUnderscoreToCamelCase());
		List<Condition> conditionList = null;
		try {
			conditionList = EntityUtil.entity2Condition(condition, isMapUnderscoreToCamelCase());
		} catch (IllegalArgumentException e) {
			LOGGER.error("build condition error", e);
			throw new MybatisArgumentException("build condition error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("build condition error", e);
			throw new MybatisArgumentException("build condition error", e);
		}
		List<Map<String, Object>> ml = selectPage(tableName, conditionList, pageBounds);
		
		List<T> tl = new ArrayList<T>();
		try {
			EntityUtil.mapList2Entity(ml, tl, c, isMapUnderscoreToCamelCase());
		} catch (InstantiationException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("convert from map to bean error", e);
			throw new MybatisDataAccessException("convert from map to bean error", e);
		}
		
		return tl;
	}
	
	@Override
	public <T> List<T> selectPage(T condition, int page, int limit) {
		return selectPage(condition, new PageBounds(page, limit));
	}
	
	@Override
	public <T> List<T> selectPage(T condition, int page, int limit, String orderExp) {
		return selectPage(condition, new PageBounds(page, limit, Order.formString(orderExp)));
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, PageBounds pageBounds) {
		return selectPage(c, null, pageBounds);
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, int page, int limit) {
		return selectPage(c, null, new PageBounds(page, limit));
	}
	
	@Override
	public <T> List<T> selectPage(Class<T> c, int page, int limit, String orderExp) {
		return selectPage(c, null, new PageBounds(page, limit, Order.formString(orderExp)));
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, PageBounds pageBounds) {
		return selectPage(tableName, null, pageBounds);
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, int page, int limit) {
		return selectPage(tableName, null, new PageBounds(page, limit));
	}
	
	@Override
	public List<Map<String, Object>> selectPage(String tableName, int page, int limit, String orderExp) {
		return selectPage(tableName, null, new PageBounds(page, limit, Order.formString(orderExp)));
	}
	
	/**
	 * 保存数据
	 * @param insertSqlBuilder
	 * @return
	 */
	private int insertCore(SqlBuilder insertSqlBuilder) {
		String insertSql = insertSqlBuilder.buildSqlString();
		Map<String, Object> sqlParam = insertSqlBuilder.getSqlParam();
		sqlParam.put("sql", insertSql);
		LOGGER.info("insert sql param is {}", JSONObject.toJSONString(sqlParam));
		return getSqlSession().insert(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_INSERT, sqlParam);
	}
	
	/**
	 * 批量保存数据
	 * 批量保存数据不设置返回值是因为，BATCH模式下，跟新返回值会丢失
	 * 官方提示如下：If the BATCH executor is in use, the update counts are being lost.
	 * @param insertSqlBuilder
	 */
	private void insertBatchCore(SqlBuilder insertSqlBuilder) {
		String insertSql = insertSqlBuilder.buildSqlString();
		Map<String, Object> sqlParam = insertSqlBuilder.getSqlParam();
		sqlParam.put("sql", insertSql);
		LOGGER.info("insert sql param is {}", JSONObject.toJSONString(sqlParam));
		
		SqlSession sqlSession = SqlSessionUtils.getSqlSession(((SqlSessionTemplate) getSqlSession()).getSqlSessionFactory(), ExecutorType.BATCH, null);
		try {
			sqlSession.insert(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_INSERT, sqlParam);
		} catch (Exception e) {
			LOGGER.error("insert sql execute error, sql is " + insertSql + ", param is " + sqlParam, e);
			throw new MybatisDataAccessException("insert sql execute error, sql is " + insertSql + ", param is " + sqlParam, e);
		}
	}
	
	/**
	 * 查询数据
	 * @param selectSqlBuilder
	 * @return
	 */
	private List<Map<String, Object>> selectCore(SqlBuilder selectSqlBuilder) {
		String sql = selectSqlBuilder.buildSqlString();
		Map<String, Object> sqlParam = selectSqlBuilder.getSqlParam();
		sqlParam.put("sql", sql);
		return getSqlSession().selectList(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_SELECT, sqlParam);
	}
	
	/**
	 * 分页查询数据
	 * @param selectSqlBuilder
	 * @param pageBounds 分页对象
	 * @return
	 */
	private List<Map<String, Object>> selectPageCore(SqlBuilder selectSqlBuilder, PageBounds pageBounds) {
		String sql = selectSqlBuilder.buildSqlString();
		Map<String, Object> sqlParam = selectSqlBuilder.getSqlParam();
		sqlParam.put("sql", sql);
		return getSqlSession().selectList(MybatisConstant.MybatisXmlConstant.NAMESPACE + MybatisConstant.MybatisXmlConstant.DML_SELECT, sqlParam, pageBounds);
	}
	
	/**
	 * 拼装主键查询条件
	 * @param tableName 表名
	 * @param pkColumnName 主键字段名
	 * @param pkColumnValue 主键字段值
	 * @return
	 */
	private Map<String, Object> buildPkCondition(String tableName, String pkColumnName, Object pkColumnValue) {
		Map<String, Object> sqlParam = new HashMap<String, Object>();
		sqlParam.put(MybatisConstant.MybatisXmlConstant.PARAM_TABLENAME, tableName);
		sqlParam.put(MybatisConstant.MybatisXmlConstant.PARAM_PK_COLUMN_NAME, pkColumnName);
		sqlParam.put(MybatisConstant.MybatisXmlConstant.PARAM_PK_VALUE, pkColumnValue);
		
		return sqlParam;
	}
	
	/**
	 * 下划线命名、camel命名是否需要转换
	 * @return
	 */
	private boolean isMapUnderscoreToCamelCase() {
		return getSqlSession().getConfiguration().isMapUnderscoreToCamelCase();
	}
	
	/**
	 * 封装批量insert集合
	 * @param l 原始数据集合
	 * @return 封装后集合，子集合为每次insert的数据集
	 */
	private List<List<Map<String, Object>>> getInsertBatchList(List<Map<String, Object>> l) {
		List<List<Map<String, Object>>> returnList = new ArrayList<List<Map<String, Object>>>();
		for(int i = 0, n = l.size() / 2 + 1; i < n; i++) {
			int fromIndex = i * INSERT_BATCH_NUM;
			int toIndex = i * INSERT_BATCH_NUM + INSERT_BATCH_NUM;
			if(toIndex > l.size()) {
				toIndex = l.size();
			}
			if(fromIndex >= toIndex) {
				break;
			}
			returnList.add(l.subList(fromIndex, toIndex));
		}
		
		return returnList;
	}
	
}
